﻿Imports System.Reflection
Imports CoreFX.Messaging
Imports CoreFX.Interfaces
Namespace Messaging
    Public Class MessageBroker
        'Credit for the original C# version goes to Team MediaPortal
        Implements IMessage
        Private Topics As New MessageTopicCollection
        Public Sub Register(ByVal Item As Object) Implements CoreFX.Interfaces.IMessage.Register
            Dim Type As Type = Item.GetType()
            [Global].Services.ServiceInstance.Get(Of ILogging).AddItem("Register: Message Registration attempt from " & Type.ToString, Logging.MessageType.General)
            ProcessSubscriptions(Item, True, Type)
            ProcessPublishers(Item, True, Type)
        End Sub
        Public Sub ProcessSubscriptions(ByVal Item As Object, ByVal Register As Boolean, ByVal type As Type)
            For Each Info As MethodInfo In type.GetMethods(BindingFlags.[Public] Or BindingFlags.NonPublic Or BindingFlags.Instance)
                Dim attributes As MessageSubscribeAttribute() = DirectCast(Info.GetCustomAttributes(GetType(MessageSubscribeAttribute), True), MessageSubscribeAttribute())
                For Each attr As MessageSubscribeAttribute In attributes
                    HandleSubscriber(Item, Register, Info, attr)
                Next
            Next
        End Sub
        Public Sub ProcessPublishers(ByVal Item As Object, ByVal Register As Boolean, ByVal type As Type)
            For Each Info As EventInfo In type.GetEvents()
                Dim attributes As MessagePublicationAttribute() = DirectCast(Info.GetCustomAttributes(GetType(MessagePublicationAttribute), True), MessagePublicationAttribute())
                For Each attr As MessagePublicationAttribute In attributes
                    HandlePublisher(Item, Register, Info, attr)
                Next
            Next
        End Sub
        Public Sub HandlePublisher(ByVal Item As Object, ByVal register As Boolean, ByVal Info As EventInfo, ByVal attr As MessagePublicationAttribute)
            Dim Topic As MessageTopic = Topics(attr.Topic)
            If register Then
                If Topic.MessageType Is Nothing Then
                    Topic.MessageType = attr.GetType
                End If
                Dim EHT As Type = Info.EventHandlerType
                Topic.AddMessagePublisher(Item, Info)
            Else
                ' TODO: Add RemovePublisher code
            End If
        End Sub
        Public Sub HandleSubscriber(ByVal Item As Object, ByVal register As Boolean, ByVal Info As MethodInfo, ByVal attr As MessageSubscribeAttribute)
            Dim Topic As MessageTopic = Topics(attr.Topic)
            If register Then
                If Topic.MessageType Is Nothing Then
                    Topic.MessageType = attr.GetType
                End If
                Dim Parameters As ParameterInfo() = Info.GetParameters()
                If Parameters.Length <> 1 Then
                    Throw New ArgumentException(String.Format("Incorrect number of parameters for message handler method {0}", Info.Name))
                End If
                Dim Parameter As ParameterInfo = Parameters(0)
                If Not Parameter.ParameterType.IsAssignableFrom(attr.GetTopic()) Then
                    ' Throw Exception
                End If
                Topic.AddListener(Item, Info)
            Else
                ' TODO: Add RemoveListener code
            End If
        End Sub
        Public Sub Send(ByVal MessageID As String, ByVal ParamArray args As Object()) Implements CoreFX.Interfaces.IMessage.Send
            Dim LogClass As ILogging = [Global].Services.Get(Of ILogging)()
            LogClass.AddItem("Send: Sending Message " & MessageID, Logging.MessageType.General)
            If Not Topics.Contains(MessageID) Then
                LogClass.AddItem("Send: Message " & MessageID & " is not registered", Logging.MessageType.General)
                Return
            End If
            Dim messageTopic As MessageTopic = Topics(MessageID)
            Dim Message As Message = Nothing
            Message = TryCast(Activator.CreateInstance(messageTopic.MessageType, args), Message)
            messageTopic.SendMessage(Message)
        End Sub
        Public Sub Unregister(ByVal Item As Object) Implements CoreFX.Interfaces.IMessage.Unregister
            ' TODO Add RemoveListener code
        End Sub
    End Class
End Namespace